package com.goxueche.plugsibrary;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

public class PluginManager {

    private static final PluginManager instance = new PluginManager();
    private Context mContext;
    private PluginApk pluginApk;

    public static PluginManager getInstance() {
        return instance;
    }

    public void init(Context context) {
        mContext = context.getApplicationContext();
    }

    public void loadApk(String apkPath) {
        PackageInfo packageInfo = mContext.getPackageManager().getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);
        if (packageInfo == null) {
            return;
        }
        DexClassLoader dexClassLoader = createDexClassLoader(apkPath);
        AssetManager assetManager = createAssetManager(apkPath);
        if (assetManager == null) {
            return;
        }
        Resources resources = createResources(assetManager, apkPath);
        pluginApk = new PluginApk(packageInfo, dexClassLoader, resources);
    }

    public PluginApk getPluginApk() {
        return pluginApk;
    }

    private DexClassLoader createDexClassLoader(String apkPath) {
        File file = mContext.getDir("dex", Context.MODE_PRIVATE);
        DexClassLoader classLoader = new DexClassLoader(apkPath, file.getAbsolutePath(), null, mContext.getClassLoader());
        return classLoader;
    }

    private AssetManager createAssetManager(String apkPath) {
        try {
            AssetManager assetManager = AssetManager.class.newInstance();
            Method method = AssetManager.class.getDeclaredMethod("addAssetPath", String.class);
            method.invoke(assetManager, apkPath);
            return assetManager;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Resources createResources(AssetManager manager, String apkPath) {
        Resources resources = new Resources(manager, mContext.getResources().getDisplayMetrics(), mContext.getResources().getConfiguration());
        return resources;
    }
}
